using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Aliyun.OSS;
using Elsa.Models;
using Jint.Native.Boolean;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TyMES.Communication;
using TyMES.MidWare;
using TyMES.Model;
using TyMES.Model.BaseInformation;
using TyMES.Model.Record;
using TyMES.PassStationCommunication;
using TyMES.ResponseModel;
using TyMES.Services;
using TyMES.ViewModel.Record.TrayBindVSNVMs;
using Newtonsoft.Json;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
using static TyMES.BaseInformation.Controllers.StationController;
using Route = TyMES.Model.BaseInformation.Route;
using static TyMES.ResponseModel.PassStationResponse;
using SQLitePCL;
using System.Text.RegularExpressions;
using TyMES.DataAccess;
using TyMES.Communication.Request;
using MaterialBindRequest = TyMES.PassStationCommunication.MaterialBindRequest;
using NPOI.HPSF;
using TyMES.Model.GetData;
using DotLiquid;
using Microsoft.EntityFrameworkCore;
using Elsa;


namespace TyMES.TemporaryClass
{
    public partial class NormalPassStationDomain 
    {
        private PassStationService _passageService;
        private ProductDataService _productDataService;
        private TrayService _trayService;
        private readonly ILogger<NormalPassStationDomain> _logger;
        private readonly IConfiguration _configuration;
        private readonly HttpService _httpService;
        //private readonly IServiceScope _serviceScope;
        private readonly WTMContext _context;
        private readonly object lockobj;
        private OrderService _orderService;
        private string _LineCode;
        private string factoryCode;
        private string mesIP;
        private string mesPort;
        private bool isopenFMES;
        private readonly IHubContext<NotificationHub> notification;
        private readonly IHubContext<InverseControlHub> inverseControl;
        private readonly PrintBarcodeService barcodeService;
        private readonly CodeCreateService codeCreateService;
        private readonly GlueDurationInspectionService glueDurationInspection;

        public NormalPassStationDomain(PassStationService passStationService, ProductDataService productDataService, OrderService orderService, TrayService trayService,
            ILogger<NormalPassStationDomain> logger, IConfiguration configuration, HttpService httpService, WTMContext _context,
         IHubContext<NotificationHub> notificationHub, IHubContext<InverseControlHub> inverseControl, PrintBarcodeService barcodeService,
            CodeCreateService codeCreateService, GlueDurationInspectionService glueDurationInspection)
        {
            this.notification = notificationHub;
            this.inverseControl = inverseControl;
            _passageService = passStationService;
            _productDataService = productDataService;
            _orderService = orderService;
            _trayService = trayService;
            _logger = logger;
            _configuration = configuration;
            _httpService = httpService;
            //_serviceScope = serviceScopeFactory.CreateScope();
            //var sp = _serviceScope.ServiceProvider;
            this._context = _context;
            this._LineCode = configuration["LineCode"];
            this.factoryCode = configuration["FactoryCode"];
            this.mesIP = configuration["MESIP"];
            this.mesPort = configuration["MESPORT"];
            this.barcodeService = barcodeService;
            this.codeCreateService = codeCreateService;
            this.glueDurationInspection = glueDurationInspection;
        }

        /// <summary>
        /// 手动扫码过站
        /// </summary>
        /// <returns></returns>
        public async Task<ResponseBase> ManualPassstation(string TZMaterialCode,string stationCode,string lineCode)
        {
            var PeggingSN = _context.DC.Set<MaterialBindRecord>().Where(x=>x.AssemblyMaterialSn ==TZMaterialCode ).OrderByDescending(x=>x.ID).FirstOrDefault();
            if (PeggingSN == null)
                return new ResponseBase(false, "并未查询到此电机条码上线时绑定的SN号");
            var passRecord = _context.DC.Set<PassStationRecord>().Where(x=>x.SnNumber==PeggingSN.SnNumber&&x.StationCode==stationCode&&x.PassStatus=="comein").FirstOrDefault();
            PassStationRequestSup stationRequestSup = new PassStationRequestSup();
            if (passRecord == null)
                stationRequestSup = await MapToPassStationRequestSup(stationCode, PeggingSN.SnNumber, "comein", lineCode,"1");
            else
                stationRequestSup = await MapToPassStationRequestSup(stationCode, PeggingSN.SnNumber, "pass", lineCode,"2");
            await PassStation(stationRequestSup);
            return new ResponseBase(true, "");
        }


        public async Task<PassStationRequestSup> MapToPassStationRequestSup(string stationCode,string SN,string passStatus,string lineCode,string reqtype)
        {
            PassStationRequestSup stationRequestSup = new PassStationRequestSup();
            stationRequestSup.snNumber = SN;
            stationRequestSup.stationCode = stationCode;
            stationRequestSup.passStatus = passStatus;
            stationRequestSup.lineCode = lineCode;
            stationRequestSup.reqType = reqtype;
            return stationRequestSup;
        }


        public async Task<Results<Ok<ResponseBase>, BadRequest<string>>> PassStation( PassStationRequestSup passStationRequestSup)
        {
            //看门日志
            {
                StationLogRecord stationLog1 = new StationLogRecord();
                stationLog1.StationCode = passStationRequestSup.stationCode;
                stationLog1.Date_Time = DateTime.Now;
                stationLog1.CreateTime = stationLog1.Date_Time;
                stationLog1.LogType = "good";
                string passType1 = string.Empty;

                if (passStationRequestSup.passStatus == "comein" && passStationRequestSup.reqType == "1")
                {
                    passType1 = "入站";
                    stationLog1.Log = $"SN:{passStationRequestSup.snNumber} 申请进站";
                }
                else if (passStationRequestSup.passStatus == "pass" && passStationRequestSup.reqType == "2")
                {
                    passType1 = "出站";
                    stationLog1.Log = $"SN:{passStationRequestSup.snNumber} 申请出站";
                }
                _context.DC.Set<StationLogRecord>().Add(stationLog1);
                await _context.DC.SaveChangesAsync();
            }

            StationLogRecord stationLog = new StationLogRecord();
            stationLog.StationCode = passStationRequestSup.stationCode;
            stationLog.Date_Time = DateTime.Now;
            stationLog.CreateTime = stationLog.Date_Time;
            stationLog.LogType = "good";

            //校验mes是否已经屏蔽
            var IsCloseMes = _context.DC.Set<CustomConfig>().Where(x => x.customProperty == "CloseMES" && x.propertyValue == "true").ToList();
            if (IsCloseMes.Count > 0)
            {
                await stationlogadd(stationLog,_LineCode, passStationRequestSup.stationCode,
                    passStationRequestSup.snNumber, "good", "mes已屏蔽");
                return TypedResults.Ok(new ResponseBase(true, "mes已屏蔽"));
            }

            string passType = string.Empty;
            if (passStationRequestSup.passStatus == "comein" && passStationRequestSup.reqType == "1")
            {
                passType = "入站";
            }
            else if (passStationRequestSup.passStatus == "pass" && passStationRequestSup.reqType == "2")
            {
                passType = "出站";
            }

            passStationRequestSup.passBeginTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            passStationRequestSup.passEndTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            passStationRequestSup.isProduct = 1;
            string linecode = string.Empty;

            try
            {
                // 查询对应子产线信息  工位信息->产线信息
                linecode = _context.DC.Set<Station>()
                    .SingleOrDefault(x => x.StationCode == passStationRequestSup.stationCode)?.LineCodeId;
                if(linecode == null)
                {
                    stationLog.LogType = "bad";
                    stationLog.Log = $"SN:{passStationRequestSup.snNumber} 申请" + passType + $"失败， 工位:{passStationRequestSup.stationCode}没有维护对应产线信息";
                    _context.DC.Set<StationLogRecord>().Add(stationLog);
                    await _context.DC.SaveChangesAsync();
                    await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, passStationRequestSup.stationCode));
                    return TypedResults.Ok(new ResponseBase(false, "此工位信息未维护"));
                }

                stationLog.LineCode = linecode;
                // 产线 工位 SN
                // 重复进出站限制
                if (!JudgeRepeat(passStationRequestSup, linecode))
                {
                    stationLog.LogType = "bad";
                    stationLog.Log = $"SN:{passStationRequestSup.snNumber} 在工位{passStationRequestSup.stationCode} " + "重复"+ passType;
                    
                    _context.DC.Set<StationLogRecord>().Add(stationLog);
                    await _context.DC.SaveChangesAsync();
                    await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, passStationRequestSup.stationCode));
                    return TypedResults.Ok(new ResponseBase(false, passStationRequestSup.snNumber + "重复"+ passType));
                }

                try
                {
                    // 查询工单信息
                    var order = (passStationRequestSup.snNumber == null || passStationRequestSup.snNumber == "") ?
                       _orderService.GetOrderInProduct(linecode, "a").Data :
                       _orderService.GetOrderInProduct(passStationRequestSup.snNumber).Data;
                    
                    //日志               
                    stationLog.LineCode = linecode;

                    string sn = "";
                    if (order != null)   // sn->工单信息
                    {
                        // 后续修改从接口获取
                        passStationRequestSup.operationCode = _passageService.ExstractOperation(passStationRequestSup.stationCode); //工序号是截取得来的 
                        passStationRequestSup.orderCode = order.OrderCode;
                        passStationRequestSup.scheduleCode = order.ScheduleCode;
                        passStationRequestSup.materialCode = order.MaterialCode;
                        passStationRequestSup.materialName = order.MaterialName;
                        passStationRequestSup.materialVersion = order.MaterialVersion;
                        passStationRequestSup.lineCode = order.Field5; //工厂产线编码，不带分段信息

                        //校验工单是否达产，若达产提示需更换新工单
                        //if (await IsOrderFulfilled(order,passStationRequestSup.operationCode))
                        //{
                        //    await stationlogadd(stationLog, order.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "工单已达目标产量，请投入新工单");
                        //    return TypedResults.Ok(new ResponseBase(false, "工单已达目标产量，请投入新工单"));
                        //}

                        //校验是否跳站
                        var IsSkip = await CheckIsSkip(passStationRequestSup);
                        if (IsSkip.Success)
                        {
                            await stationlogadd(stationLog, order.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "good", $"SN{passStationRequestSup.snNumber}在此工站执行跳站");
                            //返回跳站关键字
                            return TypedResults.Ok(new ResponseBase(true, "JustSkip"));
                        }

                        //校验是否为不良品
                        var IsBadProduct = await CheckIsBadProduct(passStationRequestSup);
                        if (IsBadProduct.Success)
                        {
                            await stationlogadd(stationLog, order.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "good", IsBadProduct.Mesg);
                            //返回跳站关键字
                            return TypedResults.Ok(new ResponseBase(true, "JustSkip"));
                        }


                        // 入站
                        if (passStationRequestSup.passStatus == "comein" && passStationRequestSup.reqType == "1")
                        {

                            var isfirststation = IsFirstOP(passStationRequestSup);
                            // 首站入站
                            if (isfirststation) //首站判断
                            {
                                ResponseBase SNRes = await GetNewSN(passStationRequestSup);

                                if (SNRes.Success == false)
                                {
                                    await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "获取虚拟SN失败" + SNRes.Mesg);
                                    return TypedResults.Ok(new ResponseBase(false, SNRes.Mesg));
                                }
                                sn = SNRes.Mesg;
                                passStationRequestSup.snNumber = sn;

                                // 添加托盘与虚拟SN、工单绑定关系信息
                                await TrayBindPost(passStationRequestSup, passStationRequestSup.TrayNumber, order, sn);

                            }
                            else if(passStationRequestSup.snNumber==""||passStationRequestSup.snNumber==null)
                            {
                                //"非首工位不允许空SN进站"
                                await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "非首工位不允许空SN进站");
                                return TypedResults.Ok(new ResponseBase(false, "非首工位不允许空SN进站"));
                            }

                            // 过站接口
                            //出货条码打印
                            try
                            {
                                var printStationCode = _context.DC.Set<CustomConfig>().Where(x => x.customProperty == "PrintZCCodeStation" && x.propertyValue == passStationRequestSup.stationCode).FirstOrDefault();
                                if (printStationCode != null)
                                {
                                    var printresult = await PrintShipmentInfo(passStationRequestSup.orderCode, passStationRequestSup.scheduleCode, passStationRequestSup.snNumber);
                                    if (!printresult.Success)
                                    {
                                        await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "打印出货条码失败" + printresult.Mesg);
                                    }
                                    
                                    passStationRequestSup.shipCode = printresult.Mesg;
                                }
                            }
                            catch (Exception ex)
                            {
                                await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "打印出货条码异常" + ex.Message);
                            }
                            //涂胶超时状态进站检验
                            var glueStationCode =await _context.DC.Set<CustomConfig>().Where(x => x.customProperty == "GlueStation" && x.propertyValue == passStationRequestSup.stationCode).FirstOrDefaultAsync();
                            if (glueStationCode != null)
                            {
                                var response = await glueDurationInspection.ComeinGlueDurationInspection();
                                if (!response.Success)
                                {
                                    //涂胶超时标志为true则拒绝进站，插入工位和过站日志
                                    await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", response.Mesg);
                                    Results<Ok<ResponseBase>, BadRequest<string>> rejectResult = TypedResults.Ok(new ResponseBase(false, response.Mesg));
                                    await AddPassStationlog(rejectResult, passStationRequestSup, "进站", order.LineCode);
                                    return rejectResult;
                                }
                            }
                            //
                            Results<Ok<ResponseBase>, BadRequest<string>> result = await PassInStation(passStationRequestSup, order,isfirststation);
                            await AddPassStationlog(result, passStationRequestSup, "进站", order.LineCode);
                            //var TrayBindResult = await RequestBindVehicle(passStationRequestSup, passStationRequestSup.TrayNumber, order);
                            return result;
                        }
                        else if (passStationRequestSup.passStatus == "pass" && passStationRequestSup.reqType == "2")
                        {
                            
                            // 入站信息校验
                            var instationInfo = this._context.DC.Set<PassStationRecord>().Where(e=>e.SnNumber == passStationRequestSup.snNumber
                                && e.StationCode == passStationRequestSup.stationCode && e.PassStatus == "comein").ToList();
                            if(instationInfo.Count == 0) 
                            {
                                await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", $"ข้อมูลการเข้าไลน์สูญหาย：{ passStationRequestSup.snNumber}无{passStationRequestSup.stationCode }的入站信息");
                                return TypedResults.Ok(new ResponseBase(false, passStationRequestSup.snNumber + "无" + passStationRequestSup.stationCode + "的入站信息"));
                            }

                            //工艺参数校验
                            var checkProcessData = await CheckProcessData(passStationRequestSup);
                            if (!checkProcessData.Success)
                            {
                                await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "ตรวจพารามิเตอร์ผิดปกติ：出站失败，生产加工参数校验异常" + checkProcessData.Mesg);
                                return TypedResults.Ok(checkProcessData);
                            }

                            //物料装配校验
                            if(passStationRequestSup.snNumber.Substring(0,7)=="DM-TG-Y")
                            {
                                //测试件过站时不进行物料校验
                            }
                            else if (!await _passageService.MaterialVerification
                                (passStationRequestSup.snNumber, order.LineCode, passStationRequestSup.operationCode,
                                    passStationRequestSup.stationCode, order.OrderCode, order.ScheduleCode))
                            {
                                await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", $"การตรวจสอบวัสดุล้มเหลว:{ passStationRequestSup.snNumber} 物料校验失败，请检查是否完成扫码");
                                return TypedResults.Ok(new ResponseBase(false, "物料校验失败"));
                            }

                            //批次物料校验和绑定
                            var batchDealResult = await _passageService.BatchBindSN(passStationRequestSup);//绑定批次信息
                            if (!batchDealResult.Success)
                            {
                                await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad",$"ข้อมูลวัสดุของล็อตผิดปกติ:{ passStationRequestSup.snNumber } 批次物料校验添加失败:{batchDealResult.Mesg}");
                                return TypedResults.Ok(new ResponseBase(false, "批次物料校验添加失败"));
                            }

                            Results<Ok<ResponseBase>, BadRequest<string>> results = await PassOutStation(passStationRequestSup, order);
                            await AddPassStationlog(results, passStationRequestSup, "出站", order.LineCode);
                            return results;

                        }
                        stationLog.LogType = "bad";
                        stationLog.Log = passStationRequestSup.snNumber + "过站状态值缺失";
                        _context.DC.Set<StationLogRecord>().Add(stationLog);
                        await _context.DC.SaveChangesAsync();
                        await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(order.LineCode, passStationRequestSup.stationCode));
                        return TypedResults.Ok(new ResponseBase(false, "The passStatus is chaos"));
                    }
                    else   // 无工单
                    {
                        stationLog.LogType = "bad";
                        stationLog.Log = "此SN并未完成上线绑定："+ passStationRequestSup.snNumber.Substring(0,17) ;
                        _context.DC.Set<StationLogRecord>().Add(stationLog);
                        await _context.DC.SaveChangesAsync();
                        await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, passStationRequestSup.stationCode));
                        return TypedResults.Ok(new ResponseBase(false, "该SN无对应工单信息"));
                    }

                }
                catch (Exception ex)
                {
                    stationLog.LogType = "bad";

                    stationLog.Log = passStationRequestSup.snNumber + " 异常:" + ex.Message.ToString();
                    _context.DC.Set<StationLogRecord>().Add(stationLog);
                    await _context.DC.SaveChangesAsync();
                    await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, passStationRequestSup.stationCode));
                    return TypedResults.Ok(new ResponseBase(false, "Get order fail"));
                }
            }
            catch(Exception ex)
            {
                stationLog.LogType = "bad";

                stationLog.Log = passStationRequestSup.snNumber + "工位信息未维护，请检查" + ex.Message.ToString();
                _context.DC.Set<StationLogRecord>().Add(stationLog);
                await _context.DC.SaveChangesAsync();
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, passStationRequestSup.stationCode));
                return TypedResults.Ok(new ResponseBase(false, "工位信息未维护"));
            }
        }


        public async Task<ResponseBase> GetNewSN(PassStationRequestSup passStationRequestSup)
        {
            ResponseBase SNRes = new ResponseBase(false, "");
            if (passStationRequestSup.stationCode == "2-OP4010-1")
            {
                //获取当前在返修工位上的产品是测试还是返修件
                string stationStatus = _context.DC.Set<CustomConfig>().AsNoTracking().Where(x => x.customProperty == "BackUpStationStatus").FirstOrDefault()?.propertyValue;
                if (stationStatus != null)
                {
                    switch (stationStatus)
                    {
                        case "test":
                            SNRes = await codeCreateService.CreateCode("test_product", 1);
                            if (SNRes.Success == false)
                            {
                                await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "获取虚拟SN失败" + SNRes.Mesg);
                                return new ResponseBase(false, SNRes.Mesg);
                            }
                            //上标准件需要提前给物料校验成功信号并且需要给生成跳站记录

                            await _passageService.ExcuteSkipOPsByModel(SNRes.Mesg, "testmodel");
                            return SNRes;
                        case "repair":
                            return await codeCreateService.CreateCode("repair_product", 1);
                        default:
                            await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "自定义配置表中维护的返修工位状态值异常");
                            return new ResponseBase(false, "自定义配置表中维护的返修工位状态值异常");
                    }
                }
                else
                {
                    await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "未在自定义配置表中维护返修工位状态值");
                    return new ResponseBase(false, "未在自定义配置表中维护返修工位状态值");
                }

            }
            else if (passStationRequestSup.stationCode == "2-OP3010-0")
            {
                //获取当前在电机上线工位是普通件，固定模板返修件，自定义模板返修件
                string stationStatus = _context.DC.Set<CustomConfig>().AsNoTracking().Where(x => x.customProperty == "TZStationStatus").FirstOrDefault()?.propertyValue;
                if (stationStatus != null)
                {
                    switch (stationStatus)
                    {
                        case "normal":
                            return await codeCreateService.CreateCode("barcode_product", 1);
                        case "repairbyconfig":
                            return await codeCreateService.CreateCode("repair_product", 1);
                        case "repairbymodel":
                            SNRes = await codeCreateService.CreateCode("repair_product", 1);
                            if (SNRes.Success == false)
                            {
                                await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "获取虚拟SN失败" + SNRes.Mesg);
                                return new ResponseBase(false, SNRes.Mesg);
                            }
                            //上标准件需要提前给物料校验成功信号并且需要给生成跳站记录

                            await _passageService.ExcuteSkipOPsByModel(SNRes.Mesg, "TZBackupModel");
                            return SNRes;
                        default:
                            await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "自定义配置表中维护的返修工位状态值异常");
                            return new ResponseBase(false, "自定义配置表中维护的返修工位状态值异常");
                    }
                }
                else
                {
                    await _passageService.stationlogadd3 (_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", "未在自定义配置表中维护返修工位状态值");
                    return new ResponseBase(false, "未在自定义配置表中维护返修工位状态值");
                }
            }
            else
            {
                return await codeCreateService.CreateCode("barcode_product", 1);
                // 获取虚拟SN失败
            }
        }

        /// <summary>
        /// 校验是否有不良记录
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckIsBadProduct(PassStationRequestSup passStationRequestSup)
        {
            var badpProductRecord = _context.DC.Set<BadProductRecord>().Where(x => x.SnNumber == passStationRequestSup.snNumber).FirstOrDefault();
            if (badpProductRecord == null)
            {
                return new ResponseBase(false, "");
            }
            return new ResponseBase(true, $"产品在工位{badpProductRecord.StationCode}被判定为不良，不良原因{badpProductRecord.DefectSource}");
        }

        /// <summary>
        /// 校验是否跳站
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckIsSkip(PassStationRequestSup passStationRequestSup)
        {
            var skipOps = _context.DC.Set<SkipOperations>().Where(x=>x.Snnumber==passStationRequestSup.snNumber&&x.OperationCode==passStationRequestSup.operationCode&&x.IsSkip==true).ToList();
            if (skipOps.Count > 0)
                return new ResponseBase(true, "此站直接跳过");
            else
                return new ResponseBase(false, "");
        }

        /// <summary>
        /// 设备加工参数和拧紧数据校验
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckProcessData(PassStationRequestSup passStationRequestSup)
        {
            var stationInfo = _context.DC.Set<Station>().Where(x=>x.StationCode==passStationRequestSup.stationCode).FirstOrDefault();
            if (stationInfo != null)
            {
                //如果工位状态为启用，那么就进行校验
                if(stationInfo.Base_Status== BaseStatusEnum.USED)
                {
                    //涂胶超时出站检验
                    var glueInspectionStation = await _context.DC.Set<CustomConfig>().Where(x => x.customProperty == "GlueInspectionStation" && x.propertyValue == passStationRequestSup.stationCode).FirstOrDefaultAsync();
                    if (glueInspectionStation != null)
                    {
                        var response = await glueDurationInspection.PassinGlueDurationInspection(passStationRequestSup.snNumber);
                        if (!response.Success)
                        {
                            //涂胶超时标志为true则拒绝出站，插入工位和过站日志
                            //await stationlogadd(stationLog, stationLog.LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", response.Mesg);
                            //Results<Ok<ResponseBase>, BadRequest<string>> rejectResult = TypedResults.Ok(new ResponseBase(false, response.Mesg));
                            //await AddPassStationlog(rejectResult, passStationRequestSup, "出站", order.LineCode);
                            return  new ResponseBase(false,response.Mesg);
                        }
                        return new ResponseBase(true,"");
                    }

                    //前箱体打标特殊处理，校验打标流水号是否重号
                    if (passStationRequestSup.stationCode == "2-OP3020-0")
                    {
                        return await Judgelasermarkingcode(passStationRequestSup);
                    }

                    //生产数据校验
                    var normalPD = await JudgeProductData(passStationRequestSup);
                    if (!normalPD.Success) 
                        return normalPD;

                    //拧紧数据校验
                    var tightenPD = await JudgeTighteningData(passStationRequestSup);
                    if(!tightenPD.Success)
                        return tightenPD;

                    return new ResponseBase(true, "");
                }
                else
                    return new ResponseBase(true, "工位工艺校验未启用");

            }
            return new ResponseBase(false, "工位信息未维护");
        }

        /// <summary>
        /// 打标工位需要校验打标号是否重码
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> Judgelasermarkingcode(PassStationRequestSup passStationRequestSup)
        {
            try
            {
                //判断是否为返修件
                var judgeIsRepair = await JudgeQXIsRepair(passStationRequestSup.snNumber, passStationRequestSup.stationCode);
                if (judgeIsRepair.Success)
                    return new ResponseBase(true, judgeIsRepair.Mesg);

                var currentlaserRecord = _context.DC.Set<ProduceDataRecord>().Where(x=>x.StationCode== passStationRequestSup.stationCode&&x.SN==passStationRequestSup.snNumber).FirstOrDefault();
                if (currentlaserRecord==null)
                {
                    return new ResponseBase(false, $"未在生产数据表中查询到SN[{passStationRequestSup.snNumber}]的打标数据,请检查是否上返修件");
                }
                var repeatlaserRecord = _context.DC.Set<ProduceDataRecord>().Where(x => x.StationCode == passStationRequestSup.stationCode && x.Data == currentlaserRecord.Data&&x.SN!=passStationRequestSup.snNumber).ToList();
                if (repeatlaserRecord.Count > 0)
                    return new ResponseBase(false, $"打标数据重号,SN[{repeatlaserRecord[0].SN}]的打标流水号也是{currentlaserRecord.Data}");
                else
                    return new ResponseBase(true, "");

            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"打标号校验异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 校验前箱体是否为返修件
        /// </summary>
        /// <param name="SN"></param>
        /// <param name="StationCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> JudgeQXIsRepair(string SN,string StationCode)
        {
            try
            {
                var materialBindRecord = _context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == SN && x.StationCode == StationCode).AsNoTracking().FirstOrDefault();
                if (materialBindRecord == null)
                    return new ResponseBase(true, $"打标号校验前未查询到前箱物料绑定记录");//这里就当返修件校验通过，等到物料校验再卡住
                
                var bindRecord_exist = _context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber != SN && x.StationCode == StationCode&&x.AssemblyMaterialSn.Contains(materialBindRecord.AssemblyMaterialSn)).AsNoTracking().FirstOrDefault();
                if(bindRecord_exist == null)
                    return new ResponseBase(false, $"非返修件");
                return new ResponseBase(true, $"返修件上线");
            }

            catch (Exception ex)
            {
                return new ResponseBase(true, $"打标校验前的返修件校验异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 生产数据表内数据校验
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> JudgeProductData(PassStationRequestSup passStationRequestSup)
        {
            var pdTemplate = _context.DC.Set<ProductDataTemplates>().Where(x => x.StationCode == passStationRequestSup.stationCode&&x.ParamCode!= "tighteningData").ToList();
            var processData = _context.DC.Set<ProduceDataRecord>().Where(x => x.StationCode == passStationRequestSup.stationCode && x.SN == passStationRequestSup.snNumber).FirstOrDefault();
            var produceDataType = _context.DC.Set<ProduceDataType>().Where(x => x.stationCode == passStationRequestSup.stationCode).FirstOrDefault();
            if (pdTemplate.Count==0)
            {
                return new ResponseBase(true, "无非拧紧数据模板");
            }

            if(processData == null)
                return new ResponseBase(false, passStationRequestSup.snNumber+"在"+passStationRequestSup.stationCode+"未上传生产数据");
            
            string[] array1 = produceDataType.nameTable.Split('*');
            string[] array2 = processData.Data.Split('*');

            //不允许数据名的定义多于实际数据量
            if (array1.Length > array2.Length)
            {
                return new ResponseBase(false, "生产数据类型管理在工位"+passStationRequestSup.stationCode+"定义数据名多于上传数据量，请重新维护");
            }

            Dictionary<string, string> dict = new Dictionary<string, string>();
            for (int i = 0; i < array1.Length; i++)
            {
                dict[array1[i]] = array2[i];
            }

            foreach (var template in pdTemplate)
            {
                string value = dict[template.ParamCodeKey];
                if(value==null) continue;
                
                if (template.StandardValue == null||template.StandardValue=="")
                {
                    //非标准值校验
                    if (!double.TryParse(value, out double realvalue))
                        return new ResponseBase(false, "读取到参数" + template.ParamCodeKey + "值" + value + "不能转化成浮点型");

                    realvalue = Math.Round(realvalue,2);

                    if (!double.TryParse(template.ParamRange1, out double upper))
                        return new ResponseBase(false,"工位"+passStationRequestSup.stationCode+"参数"+template.ParamCodeKey+ "上限值设置错误，不能转化成浮点型");
                    if(!double.TryParse(template.ParamRange2, out double floor))
                        return new ResponseBase(false, "工位" + passStationRequestSup.stationCode + "参数" + template.ParamCodeKey + "上下限值设置错误，不能转化成浮点型");
                    if(realvalue>=floor&&realvalue<=upper) continue;
                    else
                        return new ResponseBase(false, "参数"+value+"不在正常范围内,"+"合格区间为："+"["+template.ParamRange2+","+template.ParamRange1+"]");

                }
                else
                {
                    //标准值校验
                    if(value==template.StandardValue) 
                        continue;
                    else
                        return new ResponseBase(false, "标准值参数" + value+"错误,"+"标准值为："+template.StandardValue);
                }
            }
            return new ResponseBase(true, "生产加工参数校验合格");
        }

        /// <summary>
        /// 校验拧紧数据
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> JudgeTighteningData(PassStationRequestSup passStationRequestSup)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                var dataModel = _context.DC.Set<ProductDataTemplates>().Where(x=>x.StationCode==passStationRequestSup.stationCode&&x.ParamCode== "tighteningData").ToList();
                if (dataModel.Count == 0)
                    return new ResponseBase(true, "无拧紧数据模板");
                var TighteningData = _context.DC.Set<TighteningData>().Where(x => x.sn == passStationRequestSup.snNumber && x.project_name == passStationRequestSup.stationCode).ToList();
               foreach(var item in dataModel)
               {
                    if(!TighteningData.Any(x=>x.screw_id.ToString()==item.ParamCodeKey))
                        return new ResponseBase(false, $"拧紧轴:[{item.ParamCodeKey}]的数据缺失");
               }


                List<string> Screw_IDs = await ExstractAndDeduplicateScrewIDs(dataModel);
                foreach(var sid in Screw_IDs)
                {
                    var Sid_Datas = TighteningData.Where(x => x.screw_id.ToString() == sid);
                    bool sid_checkResult = false;
                    string Mesg = string.Empty;
                    foreach (var tData in Sid_Datas)
                    {
                        var NJ = dataModel.Where(x => x.ParamCodeKey == tData.screw_id.ToString() && x.ParamName == "NJ").FirstOrDefault();
                        if (NJ == null)
                        {
                            return new ResponseBase(false, "未找到在工位[" + passStationRequestSup.stationCode + "]中找到screw_id为[" + tData.screw_id.ToString() + "]的扭矩数据模板");
                        }
                        var Angel = dataModel.Where(x => x.ParamCodeKey == tData.screw_id.ToString() && x.ParamName == "Angle").FirstOrDefault();
                        if (Angel == null)
                        {
                            return new ResponseBase(false, "未找到在工位[" + passStationRequestSup.stationCode + "]中找到screw_id为[" + tData.screw_id.ToString() + "]的角度数据模板");

                        }

                        //扭矩校验
                        if (!double.TryParse(tData.torque, out double NJvalue))
                            return new ResponseBase(false, "读取到参数" + NJ.ParamCodeKey + "值" + tData.torque + "不能转化成浮点型");
                        if (!double.TryParse(NJ.ParamRange1, out double NJupper))
                            return new ResponseBase(false, "工位" + passStationRequestSup.stationCode + "参数" + NJ.ParamCodeKey + "上限值设置错误，不能转化成浮点型");
                        if (!double.TryParse(NJ.ParamRange2, out double NJfloor))
                            return new ResponseBase(false, "工位" + passStationRequestSup.stationCode + "参数" + NJ.ParamCodeKey + "上下限值设置错误，不能转化成浮点型");
                        if (NJvalue >= NJfloor && NJvalue <= NJupper)
                        {
                            //往下校验
                            
                        }
                        else
                        {
                           
                            Mesg = "工位[" + passStationRequestSup.stationCode + "]的轴[" + NJ.ParamCodeKey + "]扭矩参数" + tData.torque + "不在正常范围内," + "合格区间为：" + "[" + NJ.ParamRange2 + "," + NJ.ParamRange1 + "]";
                            continue;
                        }
                        //return new ResponseBase(false, "工位[" + passStationRequestSup.stationCode + "]的轴[" + NJ.ParamCodeKey + "]扭矩参数" + tData.torque + "不在正常范围内," + "合格区间为：" + "[" + NJ.ParamRange2 + "," + NJ.ParamRange1 + "]");

                        //角度校验
                        if (!double.TryParse(tData.angle, out double Angelvalue))
                            return new ResponseBase(false, "读取到参数" + Angel.ParamCodeKey + "值" + tData.angle + "不能转化成浮点型");
                        if (!double.TryParse(Angel.ParamRange1, out double Angleupper))
                            return new ResponseBase(false, "工位" + passStationRequestSup.stationCode + "参数" + Angel.ParamCodeKey + "上限值设置错误，不能转化成浮点型");
                        if (!double.TryParse(Angel.ParamRange2, out double Anglefloor))
                            return new ResponseBase(false, "工位" + passStationRequestSup.stationCode + "参数" + Angel.ParamCodeKey + "上下限值设置错误，不能转化成浮点型");
                        if (Angelvalue >= Anglefloor && Angelvalue <= Angleupper)
                        {
                           
                                sid_checkResult = true;
                                break;
                            
                        }
                        else
                        {
                           
                            Mesg = "工位[" + passStationRequestSup.stationCode + "]的轴[" + NJ.ParamCodeKey + "]角度参数" + tData.angle + "不在正常范围内," + "合格区间为：" + "[" + Angel.ParamRange2 + "," + Angel.ParamRange1 + "]";
                            continue;
                        }
                        
                            
                    }
                    if(!sid_checkResult)
                        return new ResponseBase(false,Mesg);
                }

               
               return new ResponseBase(true, "拧紧数据校验合格");
            }
            catch (Exception ex)
            {
               return new ResponseBase(false, ex.Message);
            }
        }

        //提取拧紧轴ID
        public async Task<List<string>> ExstractAndDeduplicateScrewIDs(List<ProductDataTemplates> datamodels)
        {
            //使用hashset去重
            var UniqueSrewIDs = new HashSet<string>();
            foreach (var datamodel in datamodels)
            {
                UniqueSrewIDs.Add(datamodel.ParamCodeKey);
            }
            return new List<string>(UniqueSrewIDs);
        }

        //校验工单是否已经达产
        public async Task<bool> IsOrderFulfilled(Order_Model order,string operationCode)
        {
            var passData = _context.DC.Set<PassStationRecord>().Where(x=>x.OrderCode== order.OrderCode&&x.OperationCode==operationCode&&x.ReqType=="2").ToList();
            int orderqty = Convert.ToInt32(order.OrderQty);
            if(orderqty>=passData.Count)
                return false;
            return true;
        }

        //添加日志并使用signalR通知前端更新
        public async Task<bool> stationlogadd(StationLogRecord stationLog, string  linecode, string stationCode,string sn,string logtype,string mesg)
        {
            stationLog.LogType = logtype;
            stationLog.StationCode = stationCode;
            stationLog.LineCode = linecode;
            stationLog.Log = mesg;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            _context.DC.Set<StationLogRecord>().Add(stationLog);
            await _context.DC.SaveChangesAsync();
            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(linecode, stationCode));
            return true;
        }

        // 限制重复出站，入站校验也校验是否出站
        private bool JudgeRepeat(PassStationRequestSup passStationRequestSup, string lineCode)
        {
            //if (passStationRequestSup.stationCode == firstStationCode && (passStationRequestSup.snNumber == "" || passStationRequestSup.snNumber == null))
            //    return true;
            if (passStationRequestSup.reqType == "1")
            {
                var res1 = this._context.DC.Set<PassStationRecord>().Where(e => e.SnNumber == passStationRequestSup.snNumber && e.LineCode == lineCode
                    && e.StationCode == passStationRequestSup.stationCode && e.ReqType == "1").ToList();

                if (res1.Count > 0) return false;
            }
            else 
            {
                var res = this._context.DC.Set<PassStationRecord>().Where(e => e.SnNumber == passStationRequestSup.snNumber && e.LineCode == lineCode
                   && e.StationCode == passStationRequestSup.stationCode && e.ReqType == "2").ToList();

                if (res.Count > 0) return false;
            } 
           
            return true;
        }

        public async Task<bool> AddPassStationlog(Results<Ok<ResponseBase>, BadRequest<string>> results, PassStationRequestSup passStationRequestSup,string INOROUT,string lineCode)
        {
            StationLogRecord stationLog = new StationLogRecord();
            stationLog.LineCode = lineCode;
            stationLog.StationCode = passStationRequestSup.stationCode;
            stationLog.Date_Time = DateTime.Now;
            stationLog.CreateTime = DateTime.Now;


            if (results.Result is Ok<ResponseBase> okObjectResult)
            {
                ResponseBase res = okObjectResult.Value as ResponseBase;
                if (res.Success == true)
                {
                    stationLog.LogType = "good";
                    stationLog.Log = $"SN:{passStationRequestSup.snNumber} " + INOROUT+ "成功";
                    _context.DC.Set<StationLogRecord>().Add(stationLog);
                    await _context.DC.SaveChangesAsync();
                }
                else
                {
                    stationLog.LogType = "bad";
                    if(passStationRequestSup.snNumber=="")
                        stationLog.Log = INOROUT + "失败" + res.Mesg;
                    else
                        stationLog.Log = $"SN:{passStationRequestSup.snNumber.Substring(0, 17)} " + INOROUT + "失败 " + res.Mesg;
                    _context.DC.Set<StationLogRecord>().Add(stationLog);
                    await _context.DC.SaveChangesAsync();
                }
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(lineCode, passStationRequestSup.stationCode));
                return true;
            }
            return false;
        }

        public async Task<TrayBindVSN> TrayBindPost(PassStationRequestSup passStationRequestSup, string TrayNumber, Order_Model order,
            string sn)
        {
            TrayBindVSN traybind = new TrayBindVSN();
            traybind.OrderCode = order.OrderCode;
            traybind.LineCode = order.LineCode;
            traybind.VSN = sn;
            traybind.BindStatus = TrayBindStatusEnum.BIND;
            traybind.TrayCode = TrayNumber;
            traybind.OnLineStation = order.StationCode;
            traybind.TrayStation = passStationRequestSup.stationCode;
            traybind.ScheduleCode = passStationRequestSup.scheduleCode;
            traybind.Uploadflag = null;
            await _context.DC.Set<TrayBindVSN>().AddAsync(traybind);

            //查询托盘状态并解绑
            //await TrayBindStateLOSS(TrayNumber);

            // 托盘绑定接口上传绑定记录
            //var firstTrayBindResult = await RequestBindVehicle(passStationRequestSup, TrayNumber,order);
            //if (firstTrayBindResult.Success == false)
            //{
            //    traybind.Uploadflag = false;
            //    _context.DC.SaveChanges();
            //}
            //else
            //{
            //    traybind.Uploadflag = true;
            //    await _context.DC.SaveChangesAsync();
            //}
            traybind.Uploadflag = false;
            await _context.DC.SaveChangesAsync();
            return traybind;
        }

        public async Task<bool> TrayBindStateLOSS(string trayNumber)
        {
            RequestBody.TraySearchBody body = new RequestBody.TraySearchBody();
            body.VehicleNumber = trayNumber;
            try
            {
                string psd = JsonConvert.SerializeObject(body);
                string value = await _httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/base/Base_Information", psd);
                TyMES.ResponseModel.PassStationResponse.TraySearchResponse response = JsonConvert.DeserializeObject< TyMES.ResponseModel.PassStationResponse.TraySearchResponse>(value);

                BindVehicleRequest bindVehicleRequest = new BindVehicleRequest();
                bindVehicleRequest.data = new List<BindVehicleRequestSup>();

                BindVehicleRequest lossrequest =await TrayBindStateSearchResult2BindVehicleRequest(response.data);
                var TrayBindResult = await _passageService.TryBindVehicleAsync(lossrequest);

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            
        }
        public async Task<ResponseComBool> RequestBindVehicle(PassStationRequestSup passStationRequestSup, string TrayNumber,Order_Model order)
        {
            if(!Regex.IsMatch(TrayNumber,"1[1-4](?:[1-9][0-9]|0[1-9])"))
            {
                return new ResponseComBool { Mesg = "请检查托盘号", Success = false };
            }
            BindVehicleRequest bindVehicleRequest = new BindVehicleRequest();
            bindVehicleRequest.data = new List<BindVehicleRequestSup>();
            BindVehicleRequestSup bindVehicleRequestSup =
                MapPassStationRequest2BindVehicleRequest(passStationRequestSup);
            bindVehicleRequest.data.Add(bindVehicleRequestSup);
            bindVehicleRequest.serviceId = "Product002_BindVehicle";
            bindVehicleRequest.factoryCode = factoryCode;
          
            if (IsFirstOP(passStationRequestSup))
            {
                if(passStationRequestSup.reqType == "1")
                    bindVehicleRequest.snBindState = "1";
                else
                    bindVehicleRequest.snBindState = "3";
            }
            else if (IsLastOP(passStationRequestSup))
            {
                if (passStationRequestSup.reqType == "2")
                    bindVehicleRequest.snBindState = "2";
                else
                    bindVehicleRequest.snBindState = "4";
            }
            else
            {
                if (passStationRequestSup.reqType == "1")
                    bindVehicleRequest.snBindState = "4";
                else
                    bindVehicleRequest.snBindState = "5";
            }
            
            bindVehicleRequest.requestTime = DateTime.Now;
            bindVehicleRequest.trayNumber = TrayNumber;
            
            var TrayBindResult = await _passageService.TryBindVehicleAsync(bindVehicleRequest);
            try
            {
                
                var tray = _context.DC.Set<Tray>().SingleOrDefault(x => x.TrayCode == TrayNumber);
                if(tray != null)
                {
                tray.TrayStatus = passStationRequestSup.operationCode == _context.DC.Set<Route>()
                .SingleOrDefault(x => x.ProductCode == order.MaterialCode)?.Field4
                && passStationRequestSup.reqType == "2" ?
                "LOSS" : "BIND";

                    tray.TrayStation = passStationRequestSup.stationCode;
                }
                else
                {
                    return new ResponseComBool { Mesg = "请检查托盘号", Success = false };
                }
            }
            catch(Exception ex)
            {
                return new ResponseComBool { Mesg = "请检查托盘号", Success = false };
            }

            
            _context.DC.SaveChanges();
            return TrayBindResult;
        }

        public async Task<Results<Ok<ResponseBase>, BadRequest<string>>> PassInStation(PassStationRequestSup passStationRequestSup, Order_Model order,bool isfirtsstation)
        {
            passStationRequestSup.passEndTime = "";
            ResponseComBool response= new ResponseComBool();
            if (isfirtsstation)
            {
                

                PassStationRequest passStationRequest = new PassStationRequest();
                passStationRequest.data = new List<PassStationRequestSup>();

                passStationRequest.data.Add(passStationRequestSup);
                passStationRequest.serviceId = "Product003_PassStation";
                passStationRequest.userId = "";
                passStationRequest.userName = "";
                passStationRequest.snBindState = "1";
                passStationRequest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                passStationRequest.factoryCode = factoryCode;
                passStationRequest.timer = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
                response = _passageService.PassFirstStationInAsync(passStationRequest,
                   Convert.ToInt32(order.Field4),
                   Convert.ToInt32(order.ScheduleQty)).Result;
                response.Mesg += passStationRequestSup.snNumber;
            }
            else
            {
                PassStationRequest passStationRequest = new PassStationRequest();
                passStationRequest.data = new List<PassStationRequestSup>();
                
                passStationRequest.data.Add(passStationRequestSup);
                passStationRequest.serviceId = "Product003_PassStation";
                passStationRequest.userId = "";
                passStationRequest.userName = "";
                passStationRequest.snBindState = "1";
                passStationRequest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                passStationRequest.factoryCode = factoryCode;
                passStationRequest.timer = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();

                SNInfo4PackageRequest request2 = new SNInfo4PackageRequest();
                request2.snNumber = passStationRequestSup.snNumber;
                request2.snStatus = "";

                ProcessParametersRequest request3 = new ProcessParametersRequest();
                request3.operationCode = passStationRequestSup.operationCode;

                response = _passageService.PassNonFirstStationInAsync(passStationRequest, request2, request3).Result;
            }
            return await _passageService.AddLMESPassStationRecord(passStationRequestSup, order, response);
        }

        public async Task<Results<Ok<ResponseBase>, BadRequest<string>>> PassOutStation(PassStationRequestSup passStationRequestSup, Order_Model order)
        {
            passStationRequestSup.passBeginTime = "";

            ResponseComBool response = new ResponseComBool();
            PassStationRequest passStationRequest = new PassStationRequest();
            if (passStationRequestSup.snNumber == "")
            {
                return TypedResults.Ok(new ResponseBase(false, "出站信息中未传入虚拟sn"));
            }
            //加入最后一站时，isproduct的赋值判断
            if (IsLastOP(passStationRequestSup))
            {
                passStationRequestSup.isProduct = 0;
                //托盘解绑
                
                try
                {
                    var traybinrecord = _context.DC.Set<TrayBindVSN>().SingleOrDefault(x => x.VSN == passStationRequestSup.snNumber);
                    traybinrecord.BindStatus = TrayBindStatusEnum.LOSS;
                    await _context.DC.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    return TypedResults.Ok(new ResponseBase(false, "出站信息中未传入虚拟sn"));
                }
                
            }
            passStationRequest.data = new List<PassStationRequestSup> { passStationRequestSup };
            passStationRequest.serviceId = "Product003_PassStation";
            passStationRequest.userId = "";
            passStationRequest.userName = "";
            passStationRequest.snBindState = "1";
            passStationRequest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            passStationRequest.factoryCode = factoryCode;
            passStationRequest.timer = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            response = _passageService.PassStationOutAsync(passStationRequest).Result;
            
            await ChangeBindOrder(passStationRequestSup);//2-OP4010执行换绑工单
            return await _passageService.AddLMESPassStationRecord(passStationRequestSup, order, response);
            
        }

        /// <summary>换绑
        /// 2-OP4010测试线上线工序需要进行工单换绑，查询到电机装配上线的工单绑定信息，完成换绑
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> ChangeBindOrder(PassStationRequestSup passStationRequestSup)
        {
            try
            {
                if (passStationRequestSup.operationCode == "2-OP4010" && passStationRequestSup.snNumber.Substring(0, 7) != "DM-TG-Y")
                {
                    //测试线上线工序非标准件执行换绑
                    var TZSnnumber = _context.DC.Set<MaterialBindRecord>().Where(x => x.StationCode == passStationRequestSup.stationCode && x.SnNumber == passStationRequestSup.snNumber).FirstOrDefault()?.AssemblyMaterialSn;
                    if (TZSnnumber == null)
                    {
                        await _passageService.stationlogadd3(_LineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "bad", $"SN:{passStationRequestSup.snNumber}未查询到其在测试线首工位的物料绑定记录");
                        return new ResponseBase(false, $"SN:{passStationRequestSup.snNumber}换绑失败,未查询到其在测试线首工位的物料绑定记录");
                    }
                    var TZtraybindvsnrecord = _context.DC.Set<TrayBindVSN>().Where(x => x.VSN == TZSnnumber).AsNoTracking().FirstOrDefault();
                    var currenttraybindvsnrecord = _context.DC.Set<TrayBindVSN>().Where(x => x.VSN == passStationRequestSup.snNumber).FirstOrDefault();

                    if (TZtraybindvsnrecord == null)
                    {
                        return new ResponseBase(false, $"未查询到电机SN:{TZSnnumber}的托盘SN绑定记录");
                    }
                    else
                    {
                        currenttraybindvsnrecord.OrderCode = TZtraybindvsnrecord.OrderCode;
                        currenttraybindvsnrecord.ScheduleCode = TZtraybindvsnrecord.ScheduleCode;
                        _context.DC.SaveChanges();
                        return new ResponseBase(true, $"SN:{passStationRequestSup.snNumber}改绑成功");
                    }
                       

                }
                return new ResponseBase(true, $"SN:{passStationRequestSup.snNumber}无需改绑");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"SN:{passStationRequestSup.snNumber}换绑失败:{ex.Message}");
            }
        }

        public async Task<string>  MillSecondsToTimeString(string millSecondsString)
        {
            try
            {
                long millseconds = new long();
                millseconds = long.Parse(millSecondsString);
                DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(millseconds);
                DateTimeOffset localDatetime = dateTimeOffset.ToLocalTime();
                return localDatetime.ToString("yyyy-MM-dd HH:mm:ss");

            }catch (Exception ex)
            {
                return "false";
            }
            
        }

        public bool IsLastOP(PassStationRequestSup passStationRequestSup)
        {
            var op = _context.DC.Set<RouteOperation>().Where(x=>x.OrderCode == passStationRequestSup.orderCode&&x.ScheduleNumber == passStationRequestSup.scheduleCode
            &&x.OperationCode==passStationRequestSup.operationCode).FirstOrDefault();
            if(op != null)
            {
                if(op.NextOperationCode == null || op.NextOperationCode == "")
                    return true;
                else
                    return false;
                
            }
            return false;
        }

        public bool IsFirstOP(PassStationRequestSup passStationRequestSup)
        {
            var op = _context.DC.Set<RouteOperation>().Where(x => x.OrderCode == passStationRequestSup.orderCode && x.ScheduleNumber == passStationRequestSup.scheduleCode
            && x.OperationCode == passStationRequestSup.operationCode).FirstOrDefault();
            if (op != null)
            {
                if (op.LastOperationCode == null || op.LastOperationCode == "0"|| op.LastOperationCode == "")
                    return true;
                else
                    return false;
            }
            return false;
        }

        public static BindVehicleRequestSup MapPassStationRequest2BindVehicleRequest(PassStationRequestSup request)
        {
            BindVehicleRequestSup bindVehicleRequest = new BindVehicleRequestSup();
            bindVehicleRequest.lineCode = request.lineCode;
            bindVehicleRequest.materialCode = request.materialCode;
            bindVehicleRequest.materialName = request.materialName;
            bindVehicleRequest.materialVersion = request.materialVersion;
            bindVehicleRequest.operationCode = request.operationCode;
            bindVehicleRequest.orderCode = request.orderCode;
            bindVehicleRequest.scheduleCode = request.scheduleCode;
            bindVehicleRequest.snNumber = request.snNumber;
            bindVehicleRequest.stationCode = request.stationCode;
            bindVehicleRequest.userId = "";
            bindVehicleRequest.userName = "";

            return bindVehicleRequest;
        }

        public async Task<BindVehicleRequest> TrayBindStateSearchResult2BindVehicleRequest(TraySearchResponseData request)
        {
            var orderInfo = _context.DC.Set<Order_Model>().Where(x=>x.OrderCode == request.orderNumber).ToList();
            BindVehicleRequestSup bindVehicleRequestsup = new BindVehicleRequestSup();

            BindVehicleRequest bindVehicleRequest = new BindVehicleRequest();
            bindVehicleRequest.data = new List<BindVehicleRequestSup>();
            if (orderInfo.Count > 0)
            {
                bindVehicleRequestsup.materialCode = orderInfo[0].MaterialCode;
                bindVehicleRequestsup.materialName = orderInfo[0].MaterialName;
                bindVehicleRequestsup.materialVersion = orderInfo[0].MaterialVersion;
                
            }
            bindVehicleRequestsup.lineCode = _LineCode;
            bindVehicleRequestsup.operationCode = request.operationCode;
            bindVehicleRequestsup.orderCode = request.orderNumber;
            bindVehicleRequestsup.scheduleCode = request.scheduleNumber;
            bindVehicleRequestsup.snNumber = request.snNumber;
            bindVehicleRequestsup.stationCode = request.stationCode;
            bindVehicleRequestsup.userId = "";
            bindVehicleRequestsup.userName = "";

            bindVehicleRequest.data.Add(bindVehicleRequestsup);
            bindVehicleRequest.trayNumber = request.vehicleNumber;
            bindVehicleRequest.factoryCode = factoryCode;
            bindVehicleRequest.snBindState = "2";
            bindVehicleRequest.serviceId = "Product002_BindVehicle";
            bindVehicleRequest.requestTime = DateTime.Now;



            return bindVehicleRequest;
        }

        public async Task<bool> UploadMaterialBindInfo(testrequest _testrequest)
        {
            

            try
            {
                bool updateflag = true;
                ///改动1
                foreach (var record in _testrequest.records)
                {
                    StationLogRecord stationLog = new StationLogRecord();
                    stationLog.Date_Time = DateTime.Now;
                    stationLog.CreateTime = DateTime.Now;
                    stationLog.LineCode = record.LineCode;
                    stationLog.StationCode = record.StationCode;

                    

                    MaterialBindRequestSup materialBindRequestSup = _passageService.MapRecord2RequestSup(record);
                    MaterialBindRequest materialBindRequest = new MaterialBindRequest();
                    materialBindRequest.data = new List<MaterialBindRequestSup> { materialBindRequestSup };
                    materialBindRequest.lineCode = _LineCode;
                    materialBindRequest.factoryCode = factoryCode;
                    materialBindRequest.serviceId = "Product004_MaterialBind";
                    materialBindRequest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    materialBindRequest.updateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    materialBindRequest.mesVersion = "";
                    materialBindRequest.uuid = "";
                    //小总成标识
                    string tag = await GetAssemblyTag(record.AssemblyMaterialCode, record.AssemblyMaterialSn);


                    try
                    {
                        FactoryAPIBase.ApiResponse uploadmaterialbindinfo = await _passageService.UploadMaterialBinding(materialBindRequest);
                        if (uploadmaterialbindinfo.Code == "000000" && uploadmaterialbindinfo.Data == "")
                        {
                            updateflag = true;
                            stationLog.LogType = "good";
                            stationLog.Log = tag + record.AssemblyMaterialSn + "绑定" + record.SnNumber + "记录，上传工厂MES成功，" + uploadmaterialbindinfo.Mesg;
                            await MaterialLogAdd(stationLog);
                            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(record.LineCode, record.StationCode));
                            
                        }
                        else
                        {
                            updateflag= false;
                            stationLog.LogType = "bad";
                            stationLog.Log = tag + record.AssemblyMaterialSn + "绑定" + record.SnNumber + "记录，上传工厂MES失败，" + uploadmaterialbindinfo.Data + uploadmaterialbindinfo.Mesg;
                            await MaterialLogAdd(stationLog);
                            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(record.LineCode, record.StationCode));
                            
                        }
                    }
                    catch (Exception ex)
                    {
                        updateflag = false;
                        stationLog.LogType = "bad";
                        stationLog.Log = tag + record.AssemblyMaterialSn + "绑定" + record.SnNumber + "失败，" + ex.Message;
                        await MaterialLogAdd(stationLog);
                        await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(record.LineCode, record.StationCode));
                        continue;
                    }
                }
                ///改动1*
                return updateflag;
            }
            catch (Exception ex)
            {
                StationLogRecord failedstationLog = new StationLogRecord();
                failedstationLog.Date_Time = DateTime.Now;
                failedstationLog.CreateTime = DateTime.Now;
                failedstationLog.StationCode = "AUTO";
                failedstationLog.LogType = "bad";
                failedstationLog.Log = ex.Message;
                await MaterialLogAdd(failedstationLog);
                return false;
            }

        }
    
        public async Task<string> GetAssemblyTag(string materialCode,string AssemblySN)
        {
            try
            {
                var TrayBindInfo = _context.DC.Set<TrayBindVSN>().SingleOrDefault(x => x.VSN == AssemblySN);
                if (TrayBindInfo == null)
                    return "";
                var orders = _context.DC.Set<Order_Model>().Where(x => x.OrderCode == TrayBindInfo.OrderCode);
                foreach (var order in orders)
                {
                    if (order.MaterialCode == materialCode)
                        return "小总成";
                }
                //if (orders.Any(order => order.MaterialCode == materialCode))
                //{
                //    return "小总成";
                //}
                return "";
            }catch (Exception ex)
            {
                return "";
            }
            
        }

        public async Task<bool> MaterialLogAdd(StationLogRecord stationLog)
        {
            var newDC = _context.CreateDC();
            newDC.Set<StationLogRecord>().Add(stationLog);
            await newDC.SaveChangesAsync();
            return true;
        }


        /// <summary>
        /// 通过工厂mes接口获取总成号
        /// </summary>
        /// <param name="orderCode"></param>
        /// <param name="scheduleCode"></param>
        /// <param name="stationCode"></param>
        /// <returns></returns>
        public async Task<ResponseShipment> GetShipmentCode(string orderCode, string scheduleCode, string stationCode)
        {
            var shipmentinfo =await GetShipmentInfo(orderCode,scheduleCode);
            if (!shipmentinfo.Success)
            {
                return new ResponseShipment(false, "", null, shipmentinfo.mesg);
            }

            ResquestBody4VirtualSN resquestBody = new ResquestBody4VirtualSN
            {
                factoryCode = factoryCode,
                serviceId = "Product001_SNCreate",
                requestTime = DateTime.Now.ToString("yy-MM-dd HH:mm:ss"),
                data = new List<TSdata>()
            };
            TSdata tsdata = new TSdata();
            tsdata.lineCode = _LineCode;
            tsdata.orderCode = orderCode;
            tsdata.scheduleCode = scheduleCode;
            tsdata.barcodeCategory = "barcode_shipment";
            tsdata.snQty = "1";
            tsdata.stationCode = stationCode;
            resquestBody.data.Add(tsdata);
            try
            {
                string psd = JsonConvert.SerializeObject(resquestBody);
                string value = await _httpService.PostDataAsync("http://"+mesIP+":"+mesPort+"/api/product/Product_Information", psd);


                VSNRes vsnres = new VSNRes();
                vsnres.data = new List<VSNdata>();
                vsnres = JsonConvert.DeserializeObject<VSNRes>(value);
                if (vsnres != null && vsnres.code == "000000")
                {
                    if (vsnres.data.Count > 0)
                    {
                        // 目前默认工厂MES只下发单个SN,下发多个后需增加存储功能，
                        // 先判断预存数量，没有预存调用工厂MES获取虚拟SN
                        return new ResponseShipment(true, vsnres.data[0].snBarcode,shipmentinfo,"获取出货信息成功");
                    }
                }
                return new ResponseShipment(false, vsnres.data[0].snBarcode, shipmentinfo, vsnres.mesg);
            }
            catch (Exception ex)
            {
                return new ResponseShipment(false, "", shipmentinfo, ex.Message);
            }
        }

        public async Task<ResponseShipmentInfo> GetShipmentInfo(string orderCode, string scheduleCode)
        {
            var orderinfo = _context.DC.Set<Order_Model>().Where(x=>x.OrderCode== orderCode&&x.ScheduleCode==scheduleCode).FirstOrDefault();
            if(orderinfo == null)
            {
                return new ResponseShipmentInfo(false, "", "", "没有对应工单信息");
            }
            GetChildLineRequest request =
                               new GetChildLineRequest(orderinfo.MaterialCode, orderinfo.MaterialVersion);
            var res = await _orderService.GetLineCodeFromFMES(request);
            string materialname = res.Data.MaterialName;
            string driverType = string.Empty;
            for (int i = 0; i < res.Data.MaterialProperties.Count; i++)
            {
                if (res.Data.MaterialProperties[i].CustomProperty == "driveType")
                {
                    driverType = res.Data.MaterialProperties[i].PropertyValue;
                    break;
                }
            }
            return new ResponseShipmentInfo(true, materialname, driverType, "获取出货条码信息成功");
        }

        public async Task<ResponseBase> PrintShipmentInfo(string orderCode, string scheduleCode, string SN)
        {
            //var printcontent =await GetShipmentCode(orderCode, scheduleCode,stationCode);
            try
            {
                var CSStation = _context.DC.Set<CustomConfig>().Where(x => x.customProperty == "CSFirstStationCode" || x.customProperty == "CSFirstStationCode-manual").OrderByDescending(x => x.ID).ToList();
                string ManualStation = CSStation[0].propertyValue;
                string AutoStation = CSStation[1].propertyValue;
                var OrginalSN = _context.DC.Set<MaterialBindRecord>().Where(x => (x.StationCode == ManualStation||x.StationCode==AutoStation )&& x.SnNumber == SN).FirstOrDefault()?.AssemblyMaterialSn;
                if (OrginalSN == null)
                {
                    return new ResponseBase(false, $"SN{SN}在测试段上线工位未执行扫码绑定");
                }

                //校验是否为NG件
                var badproductRecord_isExist = _context.DC.Set<BadProductRecord>().Where(x=>x.SnNumber == SN).Count();
                if(badproductRecord_isExist > 0)
                    return new ResponseBase(false, $"SN{SN}存在不良记录，不予执行条码打印");

                var OrderCode = _context.DC.Set<TrayBindVSN>().Where(x=>x.VSN == OrginalSN).FirstOrDefault()?.OrderCode;
                var ProductCode = _context.DC.Set<Order_Model>().Where(x=>x.OrderCode==OrderCode).FirstOrDefault().MaterialCode;
                var prodcut = _context.DC.Set<Product>().Where(x=>x.ProductCode==ProductCode).FirstOrDefault();


                await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice(SN,prodcut?.Notes+"*"+ prodcut?.ProductName, "3"));
                return new ResponseBase(true, "");
                
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }


    
        public async Task<ResponseBase> CreateCodeTest(string codeTypeName, int sqt)
        {
            return await codeCreateService.CreateShipCode(codeTypeName, sqt);
        }
    }
}
